using DeviceRepairWorkflow.Api.Data;
using DeviceRepairWorkflow.Api.Models;
using Elsa.Workflows.Runtime.Contracts;
using Elsa.Workflows.Runtime.Requests;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Text.Json;

namespace DeviceRepairWorkflow.Api.Controllers;

[ApiController]
[Route("api/[controller]")]
public class WorkflowController : ControllerBase
{
    private readonly ApplicationDbContext _context;
    private readonly IWorkflowDispatcher _workflowDispatcher;

    public WorkflowController(ApplicationDbContext context, IWorkflowDispatcher workflowDispatcher)
    {
        _context = context;
        _workflowDispatcher = workflowDispatcher;
    }

    [HttpPost("start")]
    public async Task<ActionResult> StartWorkflow([FromBody] WorkflowStartRequest request)
    {
        try
        {
            // Get repair request
            var repairRequest = await _context.RepairRequests
                .Include(r => r.Device)
                .FirstOrDefaultAsync(r => r.Id == request.RepairRequestId);

            if (repairRequest == null)
            {
                return NotFound($"Repair request with ID {request.RepairRequestId} not found");
            }

            // Create workflow instance
            var workflowInstance = new WorkflowInstance
            {
                RepairRequestId = request.RepairRequestId,
                CurrentStep = "Start",
                Status = WorkflowStatus.Running,
                CreatedAt = DateTime.Now,
                CreatedBy = request.CurrentUser
            };

            _context.WorkflowInstances.Add(workflowInstance);
            await _context.SaveChangesAsync();

            // Start Elsa workflow
            var workflowInput = new Dictionary<string, object>
            {
                ["RepairRequestId"] = request.RepairRequestId,
                ["DeviceId"] = repairRequest.DeviceId,
                ["RequestedBy"] = repairRequest.RequestedBy,
                ["WorkflowInstanceId"] = workflowInstance.Id
            };

            var startWorkflowRequest = new DispatchWorkflowDefinitionRequest
            {
                DefinitionId = "DeviceRepairWorkflow",
                Input = workflowInput
            };

                    // For now, we'll handle the workflow logic directly in the controller
        // Later we can integrate with Elsa properly
        var result = await _workflowDispatcher.DispatchAsync(startWorkflowRequest);

        return Ok(new { 
            Success = true, 
            WorkflowInstanceId = workflowInstance.Id,
            Message = "Workflow started successfully"
        });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpPost("decision")]
    public async Task<ActionResult> MakeDecision([FromBody] DecisionRequest request)
    {
        try
        {
            var workflowInstance = await _context.WorkflowInstances
                .Include(w => w.RepairRequest)
                .FirstOrDefaultAsync(w => w.Id == request.WorkflowInstanceId);

            if (workflowInstance == null)
            {
                return NotFound($"Workflow instance with ID {request.WorkflowInstanceId} not found");
            }

            // Update workflow instance
            workflowInstance.IsExternalRepair = request.IsExternalRepair;
            workflowInstance.CurrentStep = request.IsExternalRepair ? "ExternalVendorForm" : "InternalRepairForm";

            // Update repair request status
            workflowInstance.RepairRequest.Status = request.IsExternalRepair ? 
                RepairStatus.ExternalRepair : RepairStatus.InternalRepair;

            await _context.SaveChangesAsync();

            return Ok(new { 
                Success = true, 
                Message = "Decision recorded successfully",
                NextStep = workflowInstance.CurrentStep
            });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpPost("external-vendor")]
    public async Task<ActionResult> SubmitExternalVendor([FromBody] ExternalVendorRequest request)
    {
        try
        {
            var workflowInstance = await _context.WorkflowInstances
                .Include(w => w.RepairRequest)
                .FirstOrDefaultAsync(w => w.Id == request.WorkflowInstanceId);

            if (workflowInstance == null)
            {
                return NotFound($"Workflow instance with ID {request.WorkflowInstanceId} not found");
            }

            // Update workflow instance
            workflowInstance.ExternalVendorId = request.ExternalVendorId;
            workflowInstance.CurrentStep = "Completed";
            workflowInstance.Status = WorkflowStatus.Completed;
            workflowInstance.CompletedAt = DateTime.Now;

            // Update repair request status
            workflowInstance.RepairRequest.Status = RepairStatus.Completed;
            workflowInstance.RepairRequest.CompletedAt = DateTime.Now;

            await _context.SaveChangesAsync();

            return Ok(new { 
                Success = true, 
                Message = "External vendor information submitted successfully",
                WorkflowCompleted = true
            });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpPost("internal-repair")]
    public async Task<ActionResult> SubmitInternalRepair([FromBody] InternalRepairRequest request)
    {
        try
        {
            var workflowInstance = await _context.WorkflowInstances
                .FirstOrDefaultAsync(w => w.Id == request.WorkflowInstanceId);

            if (workflowInstance == null)
            {
                return NotFound($"Workflow instance with ID {request.WorkflowInstanceId} not found");
            }

            // Update workflow instance
            workflowInstance.CurrentStep = "RepairDetailsForm";

            await _context.SaveChangesAsync();

            return Ok(new { 
                Success = true, 
                Message = "Internal repair form submitted successfully",
                NextStep = workflowInstance.CurrentStep
            });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpPost("repair-details")]
    public async Task<ActionResult> SubmitRepairDetails([FromBody] RepairDetailsRequest request)
    {
        try
        {
            var workflowInstance = await _context.WorkflowInstances
                .Include(w => w.RepairRequest)
                .FirstOrDefaultAsync(w => w.Id == request.WorkflowInstanceId);

            if (workflowInstance == null)
            {
                return NotFound($"Workflow instance with ID {request.WorkflowInstanceId} not found");
            }

            // Update workflow instance
            workflowInstance.RepairContent = request.RepairContent;
            workflowInstance.RepairHours = request.RepairHours;
            workflowInstance.RepairCost = request.RepairCost;
            workflowInstance.RepairNotes = request.RepairNotes;
            workflowInstance.CurrentStep = "ApprovalPending";

            // Update repair request status
            workflowInstance.RepairRequest.Status = RepairStatus.WaitingForApproval;

            await _context.SaveChangesAsync();

            return Ok(new { 
                Success = true, 
                Message = "Repair details submitted successfully",
                NextStep = workflowInstance.CurrentStep
            });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpPost("approval")]
    public async Task<ActionResult> SubmitApproval([FromBody] ApprovalRequest request)
    {
        try
        {
            var workflowInstance = await _context.WorkflowInstances
                .Include(w => w.RepairRequest)
                .FirstOrDefaultAsync(w => w.Id == request.WorkflowInstanceId);

            if (workflowInstance == null)
            {
                return NotFound($"Workflow instance with ID {request.WorkflowInstanceId} not found");
            }

            // Update workflow instance
            workflowInstance.IsApproved = request.IsApproved;
            workflowInstance.ApprovalNotes = request.ApprovalNotes;
            workflowInstance.ApprovedBy = request.ApprovedBy;
            workflowInstance.ApprovedAt = DateTime.Now;

            if (request.IsApproved)
            {
                workflowInstance.CurrentStep = "Completed";
                workflowInstance.Status = WorkflowStatus.Completed;
                workflowInstance.CompletedAt = DateTime.Now;
                if (workflowInstance.RepairRequest != null)
                {
                    workflowInstance.RepairRequest.Status = RepairStatus.Completed;
                    workflowInstance.RepairRequest.CompletedAt = DateTime.Now;
                }
            }
            else
            {
                workflowInstance.CurrentStep = "DecisionReview";
                if (workflowInstance.RepairRequest != null)
                {
                    workflowInstance.RepairRequest.Status = RepairStatus.DecisionPending;
                }
            }

            await _context.SaveChangesAsync();

            return Ok(new { 
                Success = true, 
                Message = request.IsApproved ? "Approval granted successfully" : "Approval denied, returning to decision phase",
                WorkflowCompleted = request.IsApproved,
                NextStep = workflowInstance.CurrentStep
            });
        }
        catch (Exception ex)
        {
            return StatusCode(500, new { Error = ex.Message });
        }
    }

    [HttpGet("instance/{id}")]
    public async Task<ActionResult<WorkflowInstance>> GetWorkflowInstance(int id)
    {
        var workflowInstance = await _context.WorkflowInstances
            .Include(w => w.RepairRequest)
            .Include(w => w.RepairRequest.Device)
            .Include(w => w.ExternalVendor)
            .Include(w => w.Steps)
            .FirstOrDefaultAsync(w => w.Id == id);

        if (workflowInstance == null)
        {
            return NotFound();
        }

        return Ok(workflowInstance);
    }

    [HttpGet("instances")]
    public async Task<ActionResult<IEnumerable<WorkflowInstance>>> GetWorkflowInstances(
        [FromQuery] string? status = null,
        [FromQuery] string? currentStep = null)
    {
        var query = _context.WorkflowInstances
            .Include(w => w.RepairRequest)
            .Include(w => w.RepairRequest.Device)
            .Include(w => w.ExternalVendor)
            .AsQueryable();

        if (!string.IsNullOrEmpty(status) && Enum.TryParse<WorkflowStatus>(status, out var statusEnum))
        {
            query = query.Where(w => w.Status == statusEnum);
        }

        if (!string.IsNullOrEmpty(currentStep))
        {
            query = query.Where(w => w.CurrentStep == currentStep);
        }

        var instances = await query
            .OrderByDescending(w => w.CreatedAt)
            .ToListAsync();

        return Ok(instances);
    }

    [HttpGet("pending-tasks")]
    public async Task<ActionResult> GetPendingTasks([FromQuery] string? userRole = null)
    {
        var query = _context.WorkflowInstances
            .Include(w => w.RepairRequest)
            .Include(w => w.RepairRequest.Device)
            .Where(w => w.Status == WorkflowStatus.Running);

        // Filter by user role
        if (!string.IsNullOrEmpty(userRole))
        {
            if (userRole.ToLower() == "admin")
            {
                query = query.Where(w => w.CurrentStep == "ApprovalPending");
            }
            else if (userRole.ToLower() == "technician")
            {
                query = query.Where(w => w.CurrentStep != "ApprovalPending");
            }
        }

        var tasks = await query
            .OrderByDescending(w => w.CreatedAt)
            .Select(w => new
            {
                w.Id,
                w.RepairRequestId,
                w.CurrentStep,
                w.CreatedAt,
                RepairRequest = new
                {
                    w.RepairRequest.Id,
                    w.RepairRequest.Title,
                    w.RepairRequest.Description,
                    w.RepairRequest.Priority,
                    w.RepairRequest.Status,
                    Device = new
                    {
                        w.RepairRequest.Device.Name,
                        w.RepairRequest.Device.SerialNumber,
                        w.RepairRequest.Device.Location
                    }
                }
            })
            .ToListAsync();

        return Ok(tasks);
    }
}

// Request DTOs
public class WorkflowStartRequest
{
    public int RepairRequestId { get; set; }
    public string CurrentUser { get; set; } = string.Empty;
}

public class DecisionRequest
{
    public int WorkflowInstanceId { get; set; }
    public bool IsExternalRepair { get; set; }
}

public class ExternalVendorRequest
{
    public int WorkflowInstanceId { get; set; }
    public int ExternalVendorId { get; set; }
}

public class InternalRepairRequest
{
    public int WorkflowInstanceId { get; set; }
}

public class RepairDetailsRequest
{
    public int WorkflowInstanceId { get; set; }
    public string RepairContent { get; set; } = string.Empty;
    public int RepairHours { get; set; }
    public decimal RepairCost { get; set; }
    public string? RepairNotes { get; set; }
}

public class ApprovalRequest
{
    public int WorkflowInstanceId { get; set; }
    public bool IsApproved { get; set; }
    public string? ApprovalNotes { get; set; }
    public string ApprovedBy { get; set; } = string.Empty;
} 